// Author	: damphat@gmail.com
// Created	: 01/12/2008

#pragma once
#define _USE_MATH_DEFINES
#include <math.h>

float  round(float v);
float  round(float v, int digits);

double round(double v);
double round(double v, int digits);

float  log(float  v, float  base);
double log(double v, double base);

float  truncate(float  v);
double truncate(double v);

float  truncate(float  v, int digits);
double truncate(double v, int digits);

template<class T>
T math_abs(T v) {
	return v > 0 ? v : -v;
}

template<class T1, class T2>
T1 math_min(T1 a, T2 b) {
	return a > b ? b : a;
}

template<class T1, class T2>
T1 math_max(T1 a, T2 b) {
	return a > b ? a : b;
}

#define MATH_FUNC1(Name, CName) template<class T> static T Name(T v) { return CName(v); }
#define MATH_FUNC2(Name, CName) template<class T1, class T2> static T1 Name(T1 v1, T2 v2) { return CName(v1, v2); }

class Math {
public:
	static const double PI;
	static const double PI_2;
	static const double PI_4;
	static const double E;

public:
	MATH_FUNC1(Abs,		math_abs);
	MATH_FUNC1(Ceiling,	ceil);
	MATH_FUNC1(Floor,	floor);
	MATH_FUNC1(Round,	round);
	MATH_FUNC2(Round,	round);
	MATH_FUNC1(Truncate,	truncate);
	MATH_FUNC2(Truncate,	truncate);


	MATH_FUNC2(Min,		math_min);
	MATH_FUNC2(Max,		math_max);

	MATH_FUNC1(Acos,	acos);
	MATH_FUNC1(Asin,	asin);
	MATH_FUNC1(Atan,	atan);
	MATH_FUNC2(Atan2,	atan2);

	MATH_FUNC1(Cos,		cos);
	MATH_FUNC1(Sin,		sin);
	MATH_FUNC1(Tan,		tan);

	MATH_FUNC1(Cosh,	cosh);
	MATH_FUNC1(Sinh,	sinh);
	MATH_FUNC1(Tanh,	tanh);

	MATH_FUNC2(Pow,		pow);
	MATH_FUNC1(Sqrt,	sqrt);
	MATH_FUNC1(Exp,		exp);			// Note: Math::Exp(1) // C2668. --> Math::Exp((double)1);
	MATH_FUNC1(Log,		log);
	MATH_FUNC2(Log,		log);
	MATH_FUNC1(Log10,	log10);

	template<class T>
	static T Frexp(T v, int *expptr) { return frexp(v, expptr); }

	MATH_FUNC2(Modf, modf);
	MATH_FUNC2(IEEERemainder, fmod);	//System::Math::IEEERemainder

	template<class T>
	static T Ldexp(T v, int exp) { return ldexp(v, exp); }
};
